//
//  QHHCPManager.m
//  MUGH
//
//  Created by 李志良的mac mini on 2020/3/27.
//  Copyright © 2020 MUGH. All rights reserved.
//
/*
 修改热更新流程，
 1.静默更新。 更新过程中，不加载Html，提示更新中，更新完成后，再加载新的H5. 限定30秒，如果更新不完，就进入老版本H5。
 2.提示更新。 同上。
 3.邀请更新
 */
#import "QHHCPManager.h"
#import "NetworkUtility.h"
#import "QHUpdateViewController.h"

static QHHCPManager * _sharedManager = nil;

@interface QHHCPManager ()<SSZipArchiveDelegate>

@property (nonatomic,strong) QHUpdateViewController *updateAlert;

@property (nonatomic,strong) NSTimer *updateTimer;

@property (nonatomic,assign) BOOL isRcInvited;

@end

@implementation QHHCPManager

+ (QHHCPManager *)sharedManager{
    @synchronized(self)
    {
        if (_sharedManager == nil)
        {
            _sharedManager = [[QHHCPManager alloc] init];
        }
    }
    return _sharedManager;
}

-(id)init{
    self = [super init];
    if(self){
        self.updateCount = 0;
        self.silentUpdateIndex = 0;
        self.updateIndex = 0;
        self.wwwFolderArray = @[PAT_WWW_FOLDER_NAME,NURSE_WWW_FOLDER_NAME];//
        
        QHHCPInternalPreferences * hcpPreferences = [QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:PAT_WWW_FOLDER_NAME];
        //已有邀请码更新 ，不能再更新主版本，只能更新邀请跟新的版本
        if(hcpPreferences.isInviteCodeUpdated){
            self.wwwFolderArray = @[];//,@"NetWorkNurse"。//Customer // TrankC Branch1C
        }
        
//        if (DEBUG) {
////        //  邀请码更新 写死邀请码逻辑 。// 用完就屏蔽掉。
//            self.isRcInvited = YES;
//            self.wwwFolderArray = @[PAT_WWW_FOLDER_NAME,NURSE_WWW_FOLDER_NAME];
//            self.InviteCodes = @[@"rYAKE",@""];//fFbY8。  //trunkRC//aKasY//rYAKE//aKasHa
//        }

        self.updateAlertMessage = @"";
        self.silentUpdateInfoArray = [NSMutableArray array];
        self.silentManifestDiffArray = [NSMutableArray array];
        self.alertUpdateInfoArray = [NSMutableArray array];
        self.alertManifestDiffArray = [NSMutableArray array];
        [[NetworkUtility sharedNetworkUtility]startCheckInternetConnection];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(networkNotReachable) name:kNetworkUtilityNotReachableNotification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(MONETConnectReachable) name:kNetworkUtilityMONETConnectNotification object:nil];
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(wifiReachable) name:kNetworkUtilityWifiConnectNotification object:nil];
    }
    return self;
}

-(void)dealloc{
    [[NetworkUtility sharedNetworkUtility]stopCheckInternetConnection];
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}

-(void)resetVaraiebles
{
    self.updateCount = 0;
    self.silentUpdateIndex = 0;
    self.updateIndex = 0;
    self.bundleNumber = 0;
    self.updateAlertMessage = @"";
    [self.silentUpdateInfoArray removeAllObjects];
    [self.silentManifestDiffArray removeAllObjects];
    [self.alertUpdateInfoArray removeAllObjects];
    [self.alertManifestDiffArray removeAllObjects];
}

-(void)networkNotReachable{
    [self.updateAlertView showErrorMessage];
    self.updateAlertView.retryButton.enabled = NO;
    [[QHUpdateAlert sharedAlert]showNetworkErrorMsg:@"网络连接失败"];
    [QHUpdateAlert sharedAlert].retryButton.enabled = NO;
}

-(void)MONETConnectReachable{
    self.updateAlertView.retryButton.enabled = YES;
    [self.updateAlertView showNetWorkStatusMsg:@"Wi-Fi环境下更新更快哦～"];
    [[QHUpdateAlert sharedAlert]showNetworkErrorMsg:@"Wi-Fi环境下更新更快哦～"];
    [QHUpdateAlert sharedAlert].retryButton.enabled = YES;
}

-(void)wifiReachable{
    self.updateAlertView.retryButton.enabled = YES;
}

//邀请码更新
/*
 *  inviteCodes:邀请码集合
 *  bundleNames：www文件包名集合，Customer：患者版，NetWorkNurse：网约护士
 *  ⚠️⚠️⚠️inviteCodes，bundleNames  集合内容顺序必须一致
 *  completeBlock：结束后的回调
 */

-(void)updateWithIviteCodes:(NSArray*)inviteCodes bundleNames:(NSArray*)bundleNames andCompleteBlock:(QHHCPManagerCompleteBlock)completeBlock{
    if (!inviteCodes || !inviteCodes) {
        return;
    }
    self.isRcInvited = NO;
    self.wwwFolderArray = bundleNames;
    self.InviteCodes = inviteCodes;
    [self checkAllBundleUpdateWithMode:@"open" andCompleteBlock:completeBlock];
}

-(void)copyBundleToLocal{
    for (NSString *wwwFolderName in self.wwwFolderArray) {
        if(![QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:wwwFolderName].isCopiedToLocal)
        {
            //如果没拷贝，先拷贝s生成本地路径，就用一次
            NSDictionary * bundleChcpJson = [QHHCPConfig configFromBundle:wwwFolderName fileName:@"chcp.json"];
//            BOOL isSaveToLacal = [QHHCPFileManager copyBundleWWWToDocumentFilePath:wwwFolderName VersionName:bundleChcpJson[@"release"]];
            //h5大文件压缩后上传，客户端解压缩后使用。
            BOOL isSaveToLacal = [QHHCPFileManager copyAndUnzipBundleWWWToDocumentFilePath:wwwFolderName VersionName:bundleChcpJson[@"release"]];
            
            QHHCPInternalPreferences * inernalPreferences = [[QHHCPInternalPreferences alloc]init];
            if(isSaveToLacal)
            {
                inernalPreferences.isCopiedToLocal = YES;
                inernalPreferences.currentReleaseVersionName = bundleChcpJson[@"release"];
            }
            [inernalPreferences savePreferenceToLocalWithFolderName:wwwFolderName];
        }
    }
}

//检查与从服务获取更新信息
-(void)checkAllBundleUpdateWithMode:(NSString *)openMode andCompleteBlock:(QHHCPManagerCompleteBlock)completeBlock
{
    self.updateCompleteBlock = completeBlock;
    self.openMode = openMode;
    [self resetVaraiebles];
    
    //如果 没有可以检测的www包，需要跳过
    if (self.wwwFolderArray.count == 0) {
        if (self.updateCompleteBlock) {
            self.updateCompleteBlock(YES);
        }
        return;
    }
    // 记录 两个包是否都不需要更新。
    __block  NSInteger checkNoNeedUpdate = 0;
    //记录当前包索引
    __block  NSInteger currentBundleIndex = 0;

    //1.先copy bundle中的WWW到本地
    for (NSString *wwwFolderName in self.wwwFolderArray) {
        if(![QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:wwwFolderName].isCopiedToLocal)
        { //如果没拷贝，先拷贝s生成本地路径，就用一次
            NSDictionary * bundleChcpJson = [QHHCPConfig configFromBundle:wwwFolderName fileName:@"chcp.json"];
//            BOOL isSaveToLocal = [QHHCPFileManager copyBundleWWWToDocumentFilePath:wwwFolderName VersionName:bundleChcpJson[@"release"]];
          // 新版带压缩包的热更新
           BOOL isSaveToLocal = [QHHCPFileManager copyAndUnzipBundleWWWToDocumentFilePath:wwwFolderName VersionName:bundleChcpJson[@"release"]];
            QHHCPInternalPreferences * inernalPreferences = [[QHHCPInternalPreferences alloc]init];
            if(isSaveToLocal)
            {
                inernalPreferences.isCopiedToLocal = YES;
                inernalPreferences.currentReleaseVersionName = bundleChcpJson[@"release"];
            }
            [inernalPreferences savePreferenceToLocalWithFolderName:wwwFolderName];
        }
        // 禁止热更新
//        if (self.updateCompleteBlock) {
//            self.updateCompleteBlock(YES);
//            return;
//        }
//
        //2.请求网络接口，查询，是否需要更新
        __weak typeof(self) ws = self;
        QHHCPInternalPreferences * hcpPreferences = [QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:wwwFolderName];
        NSString * inviteCode = @"";
        if(self.InviteCodes.count > 0){
            inviteCode = self.InviteCodes[currentBundleIndex];
            currentBundleIndex++;
        }
        NSMutableDictionary *param = [NSMutableDictionary dictionary];
        [param setValue:inviteCode forKey:@"InviteCode"];
        [param setValue:[wwwFolderName stringByAppendingString:@"Zip"]  forKey:@"WWWName"];
        [param setValue:hcpPreferences.currentReleaseVersionName ? : @"" forKey:@"CurrentVersion"];
        [param setValue:App_Build?:@"" forKey:@"VersionCode"];
        [param setValue:@"IOS" forKey:@"Platform"];
        [AFNHttpTools requestWithUrl:GetVersionInfoRedis andPostDict:param andAuthToken:@"" successed:^(NSDictionary *dict) {
            if ([[dict objectForKey:@"errorcode"]isEqualToString:@"00000000"])
            {
                DebugLog(@"%@",dict);
                ws.bundleNumber++;
                id ManifestObject = dict[@"data"][@"Manifest"];
                if(dict[@"data"][@"VersionNo"] == NULL||[dict[@"data"][@"VersionNo"] isKindOfClass:[NSNull class]]||[ManifestObject isKindOfClass:[NSNull class]])
                {
                    checkNoNeedUpdate++;
                    NSString *errStr = [NSString stringWithFormat:@"当前%@版本%@，返回为NULL",param[@"WWWName"],param[@"CurrentVersion"]];
                    NSError *error = [NSError errorWithCode:1001 description:errStr];
//                    [Bugly reportError:error];
                }
                else
                {
                    QHUpdateType type = 0;
                    ws.webserviceVersionName = dict[@"data"][@"VersionNo"];
                    // 版本号相同，不用更新
                    if ([ws.webserviceVersionName isEqualToString:hcpPreferences.currentReleaseVersionName])
                    {
                        if(ws.InviteCodes.count > 0){//邀请更新
                            checkNoNeedUpdate++;
                            if(checkNoNeedUpdate==ws.InviteCodes.count){
                                [HUDHelper alertTitle:nil message:@"当前已经是最新版本，无需更新" cancel:@"好的"];
                                // 如果 用通知 发送的邀请更新来进入，则此处不用 reload， 如果是写死的邀请码更新，则此处需要reload。比如RC包，需要更新。
                                if(ws.updateCompleteBlock){
                                    ws.updateCompleteBlock(ws.isRcInvited);
                                }
                            }
                        }
                        else
                        {
                            checkNoNeedUpdate++;
                        }
                    }
                    else
                    {
                        if(![dict[@"data"][@"UpdateType"] isKindOfClass:[NSNull class]]){
                            type = (QHUpdateType )[[dict[@"data"] objectForKey:@"UpdateType"]integerValue];
                        }
                        QHHCPInternalPreferences * tempPreferences = [QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:dict[@"data"][@"WWWName"]];
                        tempPreferences.currentDownLoadingVersionName = dict[@"data"][@"VersionNo"];
                        tempPreferences.CurrentMinIosVer = [NSString stringWithFormat:@"%@",dict[@"data"][@"MinIosVer"]?:@""];
                        if(type == QHAutoUpdate && ![dict[@"data"][@"VersionNo"] isEqualToString:tempPreferences.currentReleaseVersionName])
                        {//静默
                            DeBugLog(@"静默更新202行");
                            [ws.silentUpdateInfoArray addObject:dict[@"data"]];
                            tempPreferences.hasNewVersionToUpdate = YES;
                        }
                        else if((type == QHSelectedUpdate||type==QHInviteUpdate)&&![dict[@"data"][@"VersionNo"] isEqualToString:tempPreferences.currentReleaseVersionName])
                        {
                            ws.updateAlertMessage = [ws.updateAlertMessage stringByAppendingString:dict[@"data"][@"Description"]];
                            [ws.alertUpdateInfoArray addObject:dict[@"data"]];
                            tempPreferences.hasNewVersionToUpdate = YES;
                        }
                        [tempPreferences savePreferenceToLocalWithFolderName:dict[@"data"][@"WWWName"]];
                    }
                    // 如果有两个包，两个包都的差异都检测完了，再更新
                    DeBugLog(@"静默更新216行%d",ws.bundleNumber);
                    if(ws.bundleNumber == ws.wwwFolderArray.count)
                    {//所有的包都检测完了，下一步，开始去比对，下载
                        if(ws.silentUpdateInfoArray.count > 0){
                            DeBugLog(@"静默更新219行");
                            [ws autoUpdateWWWPackagesDownLoad];
                        }
                        if(ws.alertUpdateInfoArray.count > 0){
                            [ws alertUpdateWWWPackagesDownLoad];
                        }
                    }
                }
            }
            else
            {
                ws.bundleNumber++;
                checkNoNeedUpdate++;
                DeBugLog(@"静默更新230行错误");
            }
            // 如果两个包 都不需要更新。就返回检测完成。
            if (checkNoNeedUpdate == ws.wwwFolderArray.count) {
                if (ws.updateCompleteBlock) {
                    ws.updateCompleteBlock(YES);
                }
            }
        }failed:^(NSError *err) {
            checkNoNeedUpdate++;
            // 如果两个包 都不需要更新。就返回检测完成。
            if (checkNoNeedUpdate == ws.wwwFolderArray.count)
            {
                if (ws.updateCompleteBlock)
                {
                    ws.updateCompleteBlock(YES);
                }
            }
            DeBugLog(@"%@",err);
        }];
    }
}

//静默更新
-(void)autoUpdateWWWPackagesDownLoad
{
    __weak typeof(self) ws = self;
    [QHUpdateAlertAndProgress currentProgress].TipStr = @"正在下载更新文件...";
    self.isNeedReload = YES;
    //只跳过静默更新，提示更新不跳过。
    _updateTimer = [NSTimer scheduledTimerWithTimeInterval:30.0 repeats:NO block:^(NSTimer * _Nonnull timer) {
        if (ws.updateCompleteBlock) {
    // 30秒之后， 更新完成，不用reload
            ws.isNeedReload = NO;
            [QHUpdateAlertAndProgress currentProgress].isSkipBtnTaped = YES;
            [[QHUpdateAlertAndProgress currentProgress]HideAllSubviews:YES];
            //进入老版本
            ws.updateCompleteBlock(YES);
        }
    }];
    DeBugLog(@"静默更新autoUpdateWWWPackagesDownLoad");
    for (NSDictionary * updateInfo in self.silentUpdateInfoArray) {
        id manifestObject = updateInfo[@"Manifest"];
        NSArray *manifestArr = [NSArray array];
        if (![manifestObject isKindOfClass:[NSNull class]] && [manifestObject isKindOfClass:[NSArray class]]) {
            manifestArr = updateInfo[@"Manifest"];
            [self autoUpdateWithManifest:manifestArr andWWWName:updateInfo[@"WWWName"]];
        }
        else
        {
            if (ws.updateCompleteBlock) {
        // Manifest 为空， 直接进入老板本
                ws.isNeedReload = NO;
                [QHUpdateAlertAndProgress currentProgress].isSkipBtnTaped = YES;
                [[QHUpdateAlertAndProgress currentProgress]HideAllSubviews:YES];
                //进入老版本
                ws.updateCompleteBlock(YES);
            }
        }
    }
}
//提示更新
-(void)alertUpdateWWWPackagesDownLoad
{
    // 释放计时器
    [self releaseTimer];
    [[QHUpdateAlertAndProgress currentProgress] HideAllSubviews:YES];
    __weak typeof(self) ws = self;//科瑞泰Q医全新改版升级，诚邀您进行使用体验！
    [[QHUpdateAlert sharedAlert] showAlertWithMessage:_updateAlertMessage];
    // 更新，不进入H5，等待更新完成后 load
    [QHUpdateAlert sharedAlert].updateButtonTappedBlock = ^{
        ws.isNeedReload = YES;
        for (NSDictionary * updateInfo in ws.alertUpdateInfoArray) {
            id manifestObject = updateInfo[@"Manifest"];
            NSArray *manifestArr = [NSArray array];
            if (![manifestObject isKindOfClass:[NSNull class]] && [manifestObject isKindOfClass:[NSArray class]])
            {
                manifestArr = updateInfo[@"Manifest"];
                [ws alertUpdateWithManifest:manifestArr andWWWName:updateInfo[@"WWWName"] andVersion:updateInfo[@"VersionNo"]];

            }
            else
            {
                // 这样写不对，应该是检测两个包都为空，再进入。目前已经在刚获取完结果处做了判断，这里的代码先屏蔽。
//                if (ws.updateCompleteBlock) {
//                // Manifest 为空， 直接进入老板本
//                    ws.isNeedReload = NO;
//                    [QHUpdateAlertAndProgress currentProgress].isSkipBtnTaped = YES;
//                    [[QHUpdateAlertAndProgress currentProgress]HideAllSubviews:YES];
//                    //进入老版本
//                    ws.updateCompleteBlock(YES);
//                }
            }
        }
    };
    // 拒绝更新
    [QHUpdateAlert sharedAlert].refusedButtonTappedBlock = ^{
        if (ws.updateCompleteBlock) {
            ws.updateCompleteBlock(YES);
        }
        [ws.updateAlertView hideProgress];
        ws.isNeedReload = NO;
    };
}

-(void)alertUpdateWithManifest:(NSArray *)manifestArr andWWWName:(NSString *)wwwName andVersion:(NSString *)webVersion
{
    if (_isNeedReload) {
        _updateAlertView = [QHHCPUpdateProgress sharedProgress];
        [_updateAlertView show];
    }
    XL_Weak;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSDictionary * chcpJson = [QHHCPConfig configFromLocalWithFolderName:wwwName fileName:@"chcp.json"];
        NSArray * chcpManifest = chcpJson[@"manifestjson"];
        NSMutableArray *addedFiles = [NSMutableArray array];
        NSMutableArray *changedFiles = [NSMutableArray array];
        NSMutableArray *deletedFiles = [[NSMutableArray alloc] init];

        for (NSDictionary *oldInfo in chcpManifest) {
            BOOL isDeleted = YES;
            for (NSDictionary *newInfo in manifestArr) {
                if ([oldInfo[@"file"] isEqualToString:[newInfo[@"file"] stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]]) {
                    isDeleted = NO;
                    if (![newInfo[@"hash"] isEqualToString:oldInfo[@"hash"]]) {
                        [changedFiles addObject:newInfo];
                    }
                }
            }
            if (isDeleted) {
                [deletedFiles addObject:oldInfo];
            }
        }

        for (NSDictionary *newInfo in manifestArr) {
            BOOL isFound = NO;
            for (NSDictionary *oldInfo in chcpManifest) {
                if ([[newInfo[@"file"] stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]isEqualToString:oldInfo[@"file"]]) {
                    isFound = YES;
                    break;
                }
            }
            if (!isFound) {
                [addedFiles addObject:newInfo];
            }
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            //得出比较结果
            QHHCPManifestDiff * tempManifestDiff = [[QHHCPManifestDiff alloc]initWithAddedFiles:addedFiles changedFiles:changedFiles deletedFiles:deletedFiles];
            tempManifestDiff.wwwContentFolderName = wwwName;
            [weakSelf.alertManifestDiffArray addObject:tempManifestDiff];

            weakSelf.updateFilesCount += tempManifestDiff.updateFileList.count;

            if(weakSelf.alertManifestDiffArray.count == weakSelf.alertUpdateInfoArray.count){
                QHHCPManifestDiff * hcpManifestDiff = weakSelf.alertManifestDiffArray[weakSelf.updateIndex];
                [weakSelf downLoadFilesWithManifestDiff:hcpManifestDiff];
                //文件下载错误时，在这里重新下载
                [QHHCPUpdateProgress sharedProgress].retryBtnClickBlock = ^{
                    [weakSelf downLoadFilesWithManifestDiff:hcpManifestDiff];
                };
            }
            if(weakSelf.alertManifestDiffArray.count == weakSelf.silentUpdateInfoArray.count){
                QHHCPManifestDiff * hcpManifestDiff = weakSelf.alertManifestDiffArray[weakSelf.updateIndex];
                weakSelf.updateAlertView.retryBtnClickBlock = ^{
                     [weakSelf downLoadFilesWithManifestDiff:hcpManifestDiff];
                };
                [weakSelf downLoadFilesWithManifestDiff:hcpManifestDiff];
            }
        });
    });
}

-(void)autoUpdateWithManifest:(NSArray *)manifestArr andWWWName:(NSString *)wwwName{
    DeBugLog(@"比较文件差异");
    NSDictionary * chcpJson = [QHHCPConfig configFromLocalWithFolderName:wwwName fileName:@"chcp.json"];
    NSArray * chcpManifest = chcpJson[@"manifestjson"];
    NSMutableArray *addedFiles = [NSMutableArray array];
    NSMutableArray *changedFiles = [NSMutableArray array];
    NSMutableArray *deletedFiles = [[NSMutableArray alloc] init];
    
    for (NSDictionary *oldInfo in chcpManifest) {
        BOOL isDeleted = YES;
        for (NSDictionary *newInfo in manifestArr) {
            if ([oldInfo[@"file"] isEqualToString:[newInfo[@"file"] stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]]) {
                isDeleted = NO;
                if (![newInfo[@"hash"] isEqualToString:oldInfo[@"hash"]]) {
                    [changedFiles addObject:newInfo];
                }
            }
        }
        if (isDeleted) {
            [deletedFiles addObject:oldInfo];
        }
    }
    
    for (NSDictionary *newInfo in manifestArr) {
        BOOL isFound = NO;
        for (NSDictionary *oldInfo in chcpManifest) {
            if ([[newInfo[@"file"] stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]  isEqualToString:oldInfo[@"file"]]) {
                isFound = YES;
                break;
            }
        }
        if (!isFound) {
            [addedFiles addObject:newInfo];
        }
    }
    
    //得出比较结果
    QHHCPManifestDiff * tempManifestDiff = [[QHHCPManifestDiff alloc]initWithAddedFiles:addedFiles changedFiles:changedFiles deletedFiles:deletedFiles];
    tempManifestDiff.wwwContentFolderName = wwwName;
    [self.silentManifestDiffArray addObject:tempManifestDiff];
    self.autoUpdateFilesCount += tempManifestDiff.updateFileList.count;
        //下载更新文件
    QHHCPManifestDiff * hcpManifestDiff = self.silentManifestDiffArray[_silentUpdateIndex];
    [self silentDownLoadFilesWithManifestDiff:hcpManifestDiff];
}
//提示更新的下载方法
-(void)downLoadFilesWithManifestDiff:(QHHCPManifestDiff*)manifestDiff{
    XL_Weak;
    if(manifestDiff.updateFileList.count > 0){//有需要更新文件
        //下载之前 删除之前下载一半的文件。
        NSString *downPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        downPath = [downPath stringByAppendingPathComponent:@"BufferedFile"];
        if ([[NSFileManager defaultManager]fileExistsAtPath:downPath]) {
            NSError *error;
            [[NSFileManager defaultManager]removeItemAtPath:downPath error:&error];
        }
        //下载更新文件
        QHHCPDownLoader * hcpDownLoader = [[QHHCPDownLoader alloc]initWithHCPWWWFolderName:manifestDiff.wwwContentFolderName Success:^{
            //下载成功，重新配置文件，生成新的www文件夹
            weakSelf.updateIndex++;
            weakSelf.totalUpdateProgress = manifestDiff.updateFileList.count;
            NSError * error;
            [weakSelf moveDownloadedFilesToWwwFolderWithManifestDiff:manifestDiff wwwFolderName:manifestDiff.wwwContentFolderName error:&error];

            if(weakSelf.alertManifestDiffArray.count > 0 && weakSelf.updateIndex < weakSelf.alertUpdateInfoArray.count)
            {
                [weakSelf downLoadFilesWithManifestDiff:weakSelf.alertManifestDiffArray[weakSelf.updateIndex]];
            }
            else
            {
                [weakSelf.updateAlertView hideProgress];
                if (weakSelf.updateCompleteBlock) {
                    weakSelf.updateCompleteBlock(YES);
                }
            }
        } Failed:^(NSString * _Nonnull errMsg) {
            if (errMsg.length > 0) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (weakSelf.isNeedReload) {
                        [weakSelf.updateAlertView showErrorWithMsg:errMsg];
                    }
                });
            }
        }];
        
        [hcpDownLoader downLoadUpdateFilesWithDiffArray:manifestDiff.updateFileList];
        hcpDownLoader.downloadProgressBlock = ^(float progress){
            if (weakSelf.isNeedReload) {
                float newProgress = (float)(progress+weakSelf.totalUpdateProgress)/(float)weakSelf.updateFilesCount;
                if (newProgress > 1.0) {
                    newProgress = 1.0;
                }
                [weakSelf.updateAlertView setUpdateProgress:newProgress];
                DeBugLog(@"===============>>%0.2f",(float)(progress+weakSelf.totalUpdateProgress)/(float)weakSelf.updateFilesCount);
            }
        };
    }
}

-(void)hideProgressView{
    [self.updateAlertView hideProgress];
}

//静默更新的下载方法
-(void)silentDownLoadFilesWithManifestDiff:(QHHCPManifestDiff*)manifestDiff{
    XL_Weak;
    DeBugLog(@"开始下载更新");
    [QHUpdateAlertAndProgress currentProgress].TipStr = @"正在下载资源文件...";
    if(manifestDiff.updateFileList.count > 0){//有需要更新文件
        //下载之前 删除之前下载一半的文件。
        NSString *downPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        downPath = [downPath stringByAppendingPathComponent:@"BufferedFile"];
        if ([[NSFileManager defaultManager]fileExistsAtPath:downPath]) {
            NSError *error;
            [[NSFileManager defaultManager]removeItemAtPath:downPath error:&error];
            if (error) {
                DeBugLog(@"下载一半的文件删除失败：%@",error);
            }
        }
        
        //下载更新文件
        QHHCPDownLoader * hcpDownLoader = [[QHHCPDownLoader alloc]initWithHCPWWWFolderName:manifestDiff.wwwContentFolderName Success:^{
            //下载成功，重新配置文件，生成新的www文件夹
            weakSelf.silentUpdateIndex++;
            weakSelf.totalUpdateProgress = manifestDiff.updateFileList.count;
            NSError * error;
            BOOL iscopySuccess = [weakSelf moveDownloadedFilesToWwwFolderWithManifestDiff:manifestDiff wwwFolderName:manifestDiff.wwwContentFolderName error:&error];
            // 拷贝成功后再更新下一个包
            if (iscopySuccess)
            {
                if(weakSelf.silentManifestDiffArray.count > 0 && weakSelf.silentUpdateIndex < weakSelf.silentManifestDiffArray.count)
                {
                    [weakSelf silentDownLoadFilesWithManifestDiff:weakSelf.silentManifestDiffArray[weakSelf.silentUpdateIndex]];
                }
                else
                {
                    if (weakSelf.updateCompleteBlock) {
                        DeBugLog(@"热更新准备完成 %d",weakSelf.isNeedReload);
                        [QHUpdateAlertAndProgress currentProgress].TipStr = @"下载完成";
                        [[QHUpdateAlertAndProgress currentProgress] HideAllSubviews:YES];
                        weakSelf.updateCompleteBlock(weakSelf.isNeedReload);
                        [weakSelf releaseTimer];
                     }
                }
            }
        } Failed:^(NSString * _Nonnull errMsg) {
            //文件下载失败，停止 计时，直接进入
            DeBugLog(@"%@",errMsg);
            [weakSelf releaseTimer];
            weakSelf.isNeedReload = NO;
            dispatch_async(dispatch_get_main_queue(), ^{
                [QHUpdateAlertAndProgress currentProgress].isSkipBtnTaped = YES;
                [[QHUpdateAlertAndProgress currentProgress]HideAllSubviews:YES];
            });
            if (weakSelf.updateCompleteBlock) {
                weakSelf.updateCompleteBlock(YES);
            }
        }];

        hcpDownLoader.downloadProgressBlock = ^(float progress) {
            CGFloat updateProgress = (float)(progress+weakSelf.totalUpdateProgress)/(float)weakSelf.autoUpdateFilesCount;
            [QHUpdateAlertAndProgress currentProgress].progress = updateProgress;
        };
        [hcpDownLoader downLoadUpdateFilesWithDiffArray:manifestDiff.updateFileList];
    }
}

- (BOOL)moveDownloadedFilesToWwwFolderWithManifestDiff:(QHHCPManifestDiff*)manifestDiff wwwFolderName:(NSString*)wwwFolderName error:(NSError **)error
{
    //1.先创建一个新的文件夹，并把现有www内容拷贝过来
    QHHCPInternalPreferences * hcpPreferences = [QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:wwwFolderName];
    BOOL copySuccess = [QHHCPFileManager copyCurrentWWWToNewVersionFilePath:wwwFolderName VersionName:hcpPreferences.currentDownLoadingVersionName];
    if (copySuccess)
    {
        DeBugLog(@"拷贝成功");
    }
    else
    {
        DeBugLog(@"拷贝失败");
        return copySuccess;
    }
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *updatedFiles = manifestDiff.updateFileList;
    NSString *errorMsg = nil;
    for (NSDictionary *manifestFile in updatedFiles) {
        // Force the release of the memory allocated during file copy
        @autoreleasepool {
            // determine paths to the file in installation and www folders
            if(![manifestFile[@"file"]  containsString:@"DS_Store"])
            {
                NSString * linkFilePath = [QHHCPFileManager localDowloadFilePathWithRemoteFileLink:manifestFile[@"ossurl"]];
                NSString * manifestFileName = [manifestFile[@"file"] stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
                NSString *pathInInstallationFolder = [NSString stringWithFormat:@"%@/%@",linkFilePath,manifestFileName];
                DeBugLog(@"========>>>>%@",pathInInstallationFolder.description);
                NSString *pathInWwwFolder = [[QHHCPFileManager localWWWFolderPathWithWWWFolderName:wwwFolderName VersionName:hcpPreferences.currentDownLoadingVersionName] stringByAppendingString:manifestFileName];
                if([fileManager fileExistsAtPath:pathInWwwFolder]&&![fileManager removeItemAtPath:pathInWwwFolder error:error]){
                    errorMsg = [NSString stringWithFormat:@"Failed to delete old version of the file %@ . Installation failed",
                                    manifestFile[@"file"]];
                    DeBugLog(@"%@",errorMsg);
                    break;
                }
                    
                NSURL * pathInWwwFolderURL =[NSURL URLWithString:[pathInWwwFolder stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
                NSURL *parentDirectoryPathInWwwFolder = [pathInWwwFolderURL URLByDeletingLastPathComponent];

                // if needed - create subfolders for the new file
                if (![fileManager fileExistsAtPath:parentDirectoryPathInWwwFolder.path]) {
                    if (![fileManager createDirectoryAtPath:parentDirectoryPathInWwwFolder.path withIntermediateDirectories:YES attributes:nil error:error]) {
                        errorMsg = [NSString stringWithFormat:@"Failed to create folder structure for file %@ : %@. Installation failed.",
                                        manifestFile[@"file"], [(*error) underlyingErrorLocalizedDesription]];
                        DeBugLog(@"%@",errorMsg);
                        break;
                    }
                }
 
                if(![fileManager moveItemAtPath:pathInInstallationFolder toPath:pathInWwwFolder error:error]){
                    errorMsg = [NSString stringWithFormat:@"Failed to copy file %@ into www folder. Installation failed.",
                                    manifestFile[@"file"]];
                    DeBugLog(@"%@",errorMsg);
                    break;
                }
            }
        }
    }
    
    if (errorMsg)
    {//kHCPFailedToCopyNewContentFilesErrorCode == -8
        // 更新失败之后，不用删除，下次更新时，下载文件的时候会删除。
        *error = [NSError errorWithCode:-8 description:errorMsg];
    }
    else
    {
        //  直捣黄龙解压缩法
        NSString *pathInWwwFolder = [QHHCPFileManager localWWWFolderPathWithWWWFolderName:wwwFolderName VersionName:hcpPreferences.currentDownLoadingVersionName];
        NSString *dstPath = [pathInWwwFolder stringByAppendingString:@"www"];
        // Customer
        if ([wwwFolderName isEqualToString:PAT_WWW_FOLDER_NAME]) {
            NSString *zipFilePath1 = [dstPath stringByAppendingPathComponent:@"build/main.css.zip"];
            NSString *zipFilePath2 = [dstPath stringByAppendingPathComponent:@"build/main.js.zip"];
            NSString *zipFilePath3 = [dstPath stringByAppendingPathComponent:@"build/vendor.js.zip"];
            NSArray *pathArr = @[zipFilePath1,zipFilePath2,zipFilePath3];
            for (NSString *tempPath in pathArr) {
                if ([fileManager fileExistsAtPath:tempPath]) {
                    NSString *newFolderPath = [dstPath stringByAppendingPathComponent:@"build"];
                    QHHCPFileManager *hcpManager = [[QHHCPFileManager alloc]init];
                    [hcpManager unzipFileatPath:tempPath andToPath:newFolderPath];
                    
                    NSError *deleteErr = nil;
                    [fileManager removeItemAtPath:tempPath error:&deleteErr];
                    DeBugLog(@"%@",deleteErr.domain);
                    DebugLog(@"%@解压成功",tempPath);
                }
            }
        }
        // NetWorkNurse
        if ([wwwFolderName isEqualToString:NURSE_WWW_FOLDER_NAME]) {
            NSString *zipFilePath4 = [dstPath stringByAppendingPathComponent:@"vendor.js.zip"];
            NSString *zipFilePath5 = [dstPath stringByAppendingPathComponent:@"main.js.zip"];
            NSArray *pathArr2 = @[zipFilePath4,zipFilePath5];
            for (NSString *tempPath in pathArr2) {
                if ([fileManager fileExistsAtPath:tempPath]) {
                    QHHCPFileManager *hcpManager = [[QHHCPFileManager alloc]init];
                    [hcpManager unzipFileatPath:tempPath andToPath:dstPath];
                    NSError *deleteErr = nil;
                    [fileManager removeItemAtPath:tempPath error:&deleteErr];
                    DeBugLog(@"%@",deleteErr.domain);
                    DebugLog(@"%@解压成功",tempPath);
                }
            }
        }
        
        QHHCPInternalPreferences * hcpPreferences = [QHHCPInternalPreferences loadFromUserDefaultsWithFolderName:wwwFolderName];
        // 删除旧包。
        NSError *deleteError;
        NSString *oldWwwPath = [QHHCPFileManager localWWWFolderPathWithWWWFolderName:wwwFolderName VersionName:hcpPreferences.currentReleaseVersionName];
        [[NSFileManager defaultManager]removeItemAtPath:oldWwwPath error:&deleteError];
        if (deleteError) {
            DeBugLog(@"删除%@文件错误",oldWwwPath);
        }
        hcpPreferences.currentReleaseVersionName = hcpPreferences.currentDownLoadingVersionName;
        hcpPreferences.hasNewVersionToUpdate = NO;
        hcpPreferences.releaseMinIosVer =  hcpPreferences.CurrentMinIosVer;
        [hcpPreferences savePreferenceToLocalWithFolderName:wwwFolderName];
    }
    return (*error == nil);
}

-(void)releaseTimer{
    if (_updateTimer) {
        [_updateTimer invalidate];
        _updateTimer = nil;
    }
}



@end
